﻿/*----------------------------------------------------------------
// Copyright (C) 2011 
// 版权所有。 
//
// 文件名：DrawLinkedList.cs
// 文件功能描述：组合图元
//
// 
// 创建标识：陈奕昆 2011-3-30
//
// 修改标识：
// 修改描述：
//
// 修改标识：
// 修改描述：
//----------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using DrawTools;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Common;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.Globalization;
using System.Security.Permissions;
using System.Reflection;
using KHMI.Attributes;

namespace DrawTools
{
    [Serializable]
    public class DrawLinkedList : DrawRectangle ,ISerializable
    {
        //图元链表
        private LinkedList<DrawObject> drawObjs = new LinkedList<DrawObject>();

        public LinkedList<DrawObject> DrawObjs
        {
            get { return drawObjs; }
            set { drawObjs = value; }
        }

        public Point newPoint;  //组合后的新坐标
        private string picPath = ""; //图元路径

        [ExtendCategoryAttribute("扩展设置", VectorName = "图元路径")]
        public string PicPath
        {
            get { return picPath; }
            set { picPath = value; }
        }

        private const string entryCount = "Count";
        private const string entryType = "Type";

        public DrawLinkedList()
            : this(0, 0, 1, 1)
        {
            newPoint = new Point();
        }

        public DrawLinkedList(int x, int y, int width, int height)
            : base()
        {
            Rectangle = new Rectangle(x, y, width, height);
            Initialize();
        }

        public override void SaveToStream(System.Runtime.Serialization.SerializationInfo info, int orderNumber)
        {
            info.AddValue("PicPath" + orderNumber.ToString(), PicPath);
            info.AddValue("RetHeight" + orderNumber.ToString(), 
                DrawRectangle.GetNormalizedRectangle(Rectangle).Height);
            info.AddValue("RetWidth" + orderNumber.ToString(),
                DrawRectangle.GetNormalizedRectangle(Rectangle).Width);
            base.SaveToStream(info, orderNumber);
        }

        public override void LoadFromStream(System.Runtime.Serialization.SerializationInfo info, int orderNumber)
        {
            PicPath = info.GetString("PicPath" + orderNumber.ToString());
            int height = info.GetInt32("RetHeight" + orderNumber.ToString());
            int width = info.GetInt32("RetWidth" + orderNumber.ToString());
            read();
            base.LoadFromStream(info, orderNumber);
        }

        /// <summary>
        /// Clone this instance
        /// </summary>
        public override DrawObject Clone(DrawObject drawObject)
        {
            base.Clone(drawObject);
            return this;
        }

        public void setNewPoint(Point p)
        {
            if (newPoint.X == 0)
            {
                newPoint = p;
            }
            else
            {
                if (p.X < newPoint.X)
                {
                    newPoint.X = p.X;
                }
                if (p.Y < newPoint.Y)
                {
                    newPoint.Y = p.Y;
                }
            }
        }

        /// <summary>
        /// 获取坐标
        /// </summary>
        public void getLocation()
        {            
            LinkedListNode<DrawObject> drawObject = DrawObjs.First;
            while (drawObject != null)
            {
                if (drawObject.Value is DrawLine)
                {
                    Point start = ((DrawLine)drawObject.Value).startPoint;
                    setNewPoint(start);
                }
                else if (drawObject.Value is DrawEllipse)
                {
                    Rectangle re = ((DrawEllipse)drawObject.Value).Rectangle;
                    setNewPoint(re.Location);
                }
                else if (drawObject.Value is DrawRectangle)
                {
                    Rectangle re = ((DrawRectangle)drawObject.Value).Rectangle;
                    setNewPoint(re.Location);
                }
                else if (drawObject.Value is DrawText)
                {
                    Rectangle re = ((DrawText)drawObject.Value).Rectangle;
                    setNewPoint(re.Location);
                }

                drawObject = drawObject.Next;
            }

            drawObject = DrawObjs.First;
            
            while (drawObject != null)
            {
                if (drawObject.Value is DrawLine)
                {
                    ((DrawLine)drawObject.Value).startPoint.X -= newPoint.X;
                    ((DrawLine)drawObject.Value).startPoint.Y -= newPoint.Y;
                    ((DrawLine)drawObject.Value).endPoint.X -= newPoint.X;
                    ((DrawLine)drawObject.Value).endPoint.Y -= newPoint.Y;
                }
                else if (drawObject.Value is DrawEllipse)
                {
                    Rectangle re = ((DrawEllipse)drawObject.Value).Rectangle;
                    re.X -= newPoint.X;
                    re.Y -= newPoint.Y;
                    ((DrawEllipse)drawObject.Value).Rectangle = re;
                }
                else if (drawObject.Value is DrawImage)
                {
                    Rectangle re = ((DrawImage)drawObject.Value).Rectangle;
                    re.X -= newPoint.X;
                    re.Y -= newPoint.Y;
                    ((DrawImage)drawObject.Value).Rectangle = re;
                }
                else if (drawObject.Value is DrawRectangle)
                {
                    Rectangle re = ((DrawRectangle)drawObject.Value).Rectangle;
                    re.X -= newPoint.X;
                    re.Y -= newPoint.Y;
                    ((DrawRectangle)drawObject.Value).Rectangle = re;
                }
                else if (drawObject.Value is DrawText)
                {
                    Rectangle re = ((DrawText)drawObject.Value).Rectangle;
                    re.X -= newPoint.X;
                    re.Y -= newPoint.Y;
                    ((DrawText)drawObject.Value).Rectangle = re;
                }

                drawObject = drawObject.Next;
            }

            this.Rectangle = new Rectangle(this.newPoint, new Size(50, 50));
            
        }

        /// <summary>
        /// 导出
        /// </summary>
        public void export()
        {
            FileStream fs = null;
            BinaryFormatter bf = null;
            try
            {
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.InitialDirectory = FunctionClass.getRunPath() + @"\Emf\";
                saveFileDialog.Filter = "图元文件|*.k";
                saveFileDialog.FilterIndex = 1;
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    fs = new FileStream(saveFileDialog.FileName, FileMode.OpenOrCreate);
                    bf = new BinaryFormatter();
                    bf.Serialize(fs, this);
                    fs.Close();
                    PicPath = saveFileDialog.FileName;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        protected DrawLinkedList(SerializationInfo info, StreamingContext context)
        {
            this.DrawObjs = new LinkedList<DrawObject>();

            int n = info.GetInt32(entryCount);
            string typeName;
            DrawObject drawObject;

            for (int i = 0; i < n; i++)
            {
                typeName = info.GetString(
                    String.Format(CultureInfo.InvariantCulture,
                        "{0}{1}",
                    entryType, i));

                drawObject = (DrawObject)Assembly.GetExecutingAssembly().CreateInstance(
                    typeName);

                drawObject.LoadFromStream(info, i);

                DrawObjs.AddLast(drawObject);
            }

        }

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="path"></param>
        public void read()
        {
            try
            {
                FileStream fs = new FileStream(PicPath, FileMode.Open);
                BinaryFormatter bf = null;
                bf = new BinaryFormatter();
                //反序列化后给属性赋值   
                DrawObjs = ((DrawLinkedList)bf.Deserialize(fs)).DrawObjs;
                fs.Close();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public override void Draw(Graphics g)
        {
            try
            {
                Pen pen = null;
                Point zPoint = new Point();
                zPoint.X = DrawRectangle.GetNormalizedRectangle(Rectangle).X;
                zPoint.Y = DrawRectangle.GetNormalizedRectangle(Rectangle).Y;

                LinkedListNode<DrawObject> drawObject = DrawObjs.First;
                while (drawObject != null)
                {
                    pen = new Pen(((DrawObject)drawObject.Value).Color,
                            ((DrawObject)drawObject.Value).PenWidth);
                    if (drawObject.Value is DrawLine)
                    {
                        Point start = ((DrawLine)drawObject.Value).startPoint;
                        setNewPoint(start);
                        Point end = ((DrawLine)drawObject.Value).endPoint;
                        setNewPoint(end);
                        FunctionClass.PointAdd(ref start, zPoint);
                        FunctionClass.PointAdd(ref end, zPoint);
                        g.DrawLine(pen, start, end);
                    }
                    else if (drawObject.Value is DrawEllipse)
                    {
                        Rectangle re = ((DrawEllipse)drawObject.Value).Rectangle;
                        setNewPoint(re.Location);
                        FunctionClass.RectangleAdd(ref re, zPoint);

                        if (((DrawObject)drawObject.Value).PenWidth > 0)
                        {
                            g.DrawEllipse(pen, re);
                        } 
                        
                        g.FillEllipse(((DrawEllipse)drawObject.Value).getBrush(re, DrawType.Ellipse), re);
                    }
                    else if (drawObject.Value is DrawText)
                    {
                        Rectangle re = ((DrawText)drawObject.Value).Rectangle;
                        setNewPoint(re.Location);
                        FunctionClass.RectangleAdd(ref re, zPoint);
                        g.DrawString(((DrawText)drawObject.Value).ShowText, ((DrawText)drawObject.Value).Font,
                            null, re);
                    }
                    else if (drawObject.Value is DrawImage)
                    {
                        Rectangle re = ((DrawImage)drawObject.Value).Rectangle;
                        setNewPoint(re.Location);
                        FunctionClass.RectangleAdd(ref re, zPoint);
                        g.DrawImage(Image.FromFile(((DrawImage)drawObject.Value).ImagePath), re);
                    }
                    else if (drawObject.Value is DrawRectangle)
                    {
                        Rectangle re = ((DrawRectangle)drawObject.Value).Rectangle;
                        setNewPoint(re.Location);
                        FunctionClass.RectangleAdd(ref re, zPoint);

                        if (((DrawObject)drawObject.Value).PenWidth > 0)
                        {
                            g.DrawRectangle(pen, re);
                        } 
                        
                        g.FillRectangle(((DrawRectangle)drawObject.Value).getBrush(re, 
                            DrawType.Ellipse), re);
                    }
                    drawObject = drawObject.Next;
                }
                pen.Dispose();
            }
            catch (System.Exception ex)
            {
                throw ex;
            }

        }

        [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(entryCount, DrawObjs.Count);

            int i = 0;

            foreach (DrawObject o in DrawObjs)
            {
                info.AddValue(
                    String.Format(CultureInfo.InvariantCulture,
                        "{0}{1}",
                        entryType, i),
                    o.GetType().FullName);

                o.SaveToStream(info, i);

                i++;
            }
        }
    }
}
